package com.sgzn.sgpay.service.tcp.impl;

import com.sgzn.sgpay.enums.AppName;
import com.sgzn.sgpay.enums.EnumDeviceState;
import com.sgzn.sgpay.enums.EnumLoginCheckResponseResult;
import com.sgzn.sgpay.model.request.SgsDeviceQueryRequest;
import com.sgzn.sgpay.model.request.SgsDeviceUpdateRequest;
import com.sgzn.sgpay.model.response.SgsResultResponse;
import com.sgzn.sgpay.model.response.vo.DeviceInfoVo;
import com.sgzn.sgpay.service.tcp.SgTcpProtocolHead;
import com.sgzn.sgpay.service.tcp.SgTcpServer;
import com.sgzn.sgpay.service.tcp.api.TcpLoginService;
import com.sgzn.sgpay.service.tcp.model.TcpLoginCheckRequest;
import com.sgzn.sgpay.service.tcp.model.TcpLoginCheckResponse;
import com.sgzn.sgpay.service.tcp.model.TcpLoginRequest;
import com.sgzn.sgpay.service.tcp.model.TcpLoginResponse;
import com.sgzn.sgpay.service.tcp.util.DateUtil;
import com.sgzn.sgpay.util.SerialNoUtil;
import com.sgzn.sgpay.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.net.Socket;
import java.util.Date;


/**
 * Created by xxjs-gd-llf
 * DATETIME:2018/4/18 17:40
 * Description: 登录服务
 */
@Slf4j
@Service
public class TcpLoginServiceImpl implements TcpLoginService {


    /**
     * 登录回复
     * @param recvBuffer
     */
    @Override
    public  void tcpAnswerLogin(String recvBuffer, Socket socket){
        try {
            //解析协议
            TcpLoginRequest tcpLoginRequest = decodeLoginBuffer(recvBuffer);

            //保存Socket
            SgTcpServer.socketList.put(tcpLoginRequest.getDeviceId(),socket);


            //组装发送报文
            TcpLoginResponse tcpLoginResponse = AssembleLoginResponseData(tcpLoginRequest);

            //保存6位随机字符串
            SgTcpServer.registerCodeMap.put(tcpLoginResponse.getDeviceId(),"111111");

            //回复报文

            log.info("发送登录请求响应报文{} " +tcpLoginResponse.toString() );
            socket.getOutputStream().write(tcpLoginResponse.toString().getBytes("UTF-8"));
        }catch (IOException e ){
            e.printStackTrace();
        }

    }

    /**
     * 答复LoginCheck请求
     * @param recvBuffer
     * @param socket
     */

    @Override
    public void tcpAnswerCheckLogin(String recvBuffer, Socket socket){
        //解析协议
        TcpLoginCheckRequest tcpLoginCheckRequest = decodeLoginCheckBuffer(recvBuffer);

        //保存Socket
        SgTcpServer.socketList.put(tcpLoginCheckRequest.getDeviceId(),socket);


        //组装发送报文
       TcpLoginCheckResponse tcpLoginCheckResponse = AssembleLoginCheckResponseData(tcpLoginCheckRequest);

        //回复报文
        try {
            log.info("发送登录认证响应报文{} " +tcpLoginCheckResponse.toString() );
            socket.getOutputStream().write(tcpLoginCheckResponse.toString().getBytes("UTF-8"));
        }catch (IOException e ){
            e.printStackTrace();
        }

        //更新设备在线状态
        updateDeviceState( tcpLoginCheckResponse.getDeviceId(),tcpLoginCheckResponse.getCheckStat() );

        //开始计数
        SgTcpServer.heartBeatCountMap.put(tcpLoginCheckResponse.getDeviceId(),0);

    }

    /**
     * 解析Login协议
     * @param recvBuffer
     * @return
     */
    private TcpLoginRequest decodeLoginBuffer(String recvBuffer ){
        TcpLoginRequest tcpLoginRequest = new TcpLoginRequest();

        //命令代码
        tcpLoginRequest.setCommandCode(recvBuffer.split(SgTcpProtocolHead.TCP_PROTOCOL_SEPERATOR)[1] );

        //设备ID
        tcpLoginRequest.setDeviceId( recvBuffer.split(SgTcpProtocolHead.TCP_PROTOCOL_SEPERATOR)[2] );

        //校验和
        tcpLoginRequest.setCheckSumCode(recvBuffer.split(SgTcpProtocolHead.TCP_PROTOCOL_SEPERATOR)[3]);

        //校验和检查
        if(!tcpLoginRequest.getCheckSumCode().equals(SgTcpProtocolHead.DEFAULT_PROTOCOL_CHECKSUM )){

            log.info("校验和错误. {},{}",tcpLoginRequest.getCheckSumCode(),SgTcpProtocolHead.DEFAULT_PROTOCOL_CHECKSUM);
            return  null;
        }

        return  tcpLoginRequest;
    }


    /**
     * 组装Login响应报文
     * @param tcpLoginRequest
     * @return
     */
    private TcpLoginResponse AssembleLoginResponseData(TcpLoginRequest tcpLoginRequest) {
        log.info("TcpLoginServiceImpl tcpLoginRequest：{}", tcpLoginRequest.toString());
        //应答
        TcpLoginResponse tcpLoginResponse = new TcpLoginResponse();
        tcpLoginResponse.setBeginCode(SgTcpProtocolHead.TCP_PROTOCOL_HEAD);
        tcpLoginResponse.setCommandCode(SgTcpProtocolHead.TCP_LOGIN_RESPONSE);
        tcpLoginResponse.setDeviceId( tcpLoginRequest.getDeviceId() );
//        tcpLoginResponse.setRandomRegisterCode(RandomUtil.generateRandomNumber(6)); //生成6位随机数

        tcpLoginResponse.setRandomRegisterCode("111111"); //生成6位随机数

        tcpLoginResponse.setCheckSumCode(SgTcpProtocolHead.DEFAULT_PROTOCOL_CHECKSUM);
        tcpLoginResponse.setEndCode(SgTcpProtocolHead.TCP_PROTOCOL_END);
        log.info("TcpLoginServiceImpl tcpLoginResponse.getRandomRegisterCode()：{}", tcpLoginResponse.getRandomRegisterCode());
        return  tcpLoginResponse;
    }


    /**
     * 解析LoginCheck协议
     * @param recvBuffer
     * @return
     */
    private TcpLoginCheckRequest decodeLoginCheckBuffer(String recvBuffer ){
        TcpLoginCheckRequest  tcpLoginCheckRequest = new TcpLoginCheckRequest();
        //命令代码
        tcpLoginCheckRequest.setCommandCode(recvBuffer.split(SgTcpProtocolHead.TCP_PROTOCOL_SEPERATOR)[1] );

        //设备ID
        tcpLoginCheckRequest.setDeviceId( recvBuffer.split(SgTcpProtocolHead.TCP_PROTOCOL_SEPERATOR)[2] );

        //认证验证码
        tcpLoginCheckRequest.setCheckRegisterCode( recvBuffer.split(SgTcpProtocolHead.TCP_PROTOCOL_SEPERATOR)[3] );


        //校验和
        tcpLoginCheckRequest.setCheckSumCode(recvBuffer.split(SgTcpProtocolHead.TCP_PROTOCOL_SEPERATOR)[4]);

        //校验和检查
        if(!tcpLoginCheckRequest.getCheckSumCode().equals(SgTcpProtocolHead.DEFAULT_PROTOCOL_CHECKSUM )){
            log.info("校验和错误. {},{}",tcpLoginCheckRequest.getCheckSumCode(),SgTcpProtocolHead.DEFAULT_PROTOCOL_CHECKSUM);
            return  null;
        }

        return  tcpLoginCheckRequest;
    }


    /**
     * 组装LoginCheck响应报文
     * @param tcpLoginCheckRequest
     * @return
     */
    private TcpLoginCheckResponse AssembleLoginCheckResponseData(TcpLoginCheckRequest tcpLoginCheckRequest) {
        //应答
        TcpLoginCheckResponse tcpLoginCheckResponse = new TcpLoginCheckResponse();
        tcpLoginCheckResponse.setBeginCode(SgTcpProtocolHead.TCP_PROTOCOL_HEAD);
        tcpLoginCheckResponse.setCommandCode(SgTcpProtocolHead.TCP_LOGIN_CHECK_RESPONSE);
        tcpLoginCheckResponse.setDeviceId( tcpLoginCheckRequest.getDeviceId() );


        //判断返回的注册码是否符合算法
        tcpLoginCheckResponse.setCheckStat(
                getCheckState(  tcpLoginCheckRequest.getDeviceId(),
                                SgTcpServer.registerCodeMap.get(tcpLoginCheckRequest.getDeviceId()),
                                tcpLoginCheckRequest.getCheckRegisterCode() ));

        tcpLoginCheckResponse.setCheckTime(DateUtil.getCurrent(DateUtil.YMDHMS));
        tcpLoginCheckResponse.setCheckSumCode(SgTcpProtocolHead.DEFAULT_PROTOCOL_CHECKSUM);
        tcpLoginCheckResponse.setEndCode(SgTcpProtocolHead.TCP_PROTOCOL_END);
        return  tcpLoginCheckResponse;
    }

    /**
     * 核实随机字符串算法
     * @param sendCode
     * @param recvCode
     * @return
     */
    private String getCheckState(String deviceId,String sendCode, String recvCode){

        SgsResultResponse<DeviceInfoVo> sgsResultResponse ;
        SgsDeviceQueryRequest sgsDeviceQueryRequest = new SgsDeviceQueryRequest();
        sgsDeviceQueryRequest.setReqTime(new Date());
        sgsDeviceQueryRequest.setLoginChannel(AppName.SGT.getNumber());
        sgsDeviceQueryRequest.setInitiationID( SerialNoUtil.generateSerialNo(AppName.SGT));
        sgsDeviceQueryRequest.setDeviceId(deviceId );
        sgsDeviceQueryRequest.setUserId("1807141034060290"); //请求对象有问题
        sgsResultResponse = SgTcpServer.sgsDeviceService.queryDeviceInfo(sgsDeviceQueryRequest);
        if (sgsResultResponse.getResult() == null ){
            log.info("设备{}未注册",deviceId);
            return EnumLoginCheckResponseResult.UNREGISTER.getStateCode();
        }
        if( sendCode.equals(StringUtil.reverse(recvCode)) ){
            log.info("验证码校验通过{},{}",sendCode,recvCode);
             return EnumLoginCheckResponseResult.SUCCESS.getStateCode();
        } else {
            log.info("验证码校验不通过{},{}",sendCode,recvCode);
             return EnumLoginCheckResponseResult.FAILURE.getStateCode();
        }

    }



    /**
     * 更新设备为在线状态
     */

    private  void updateDeviceState(String deviceId,String deviceState){
            //更新设备状态
            SgsDeviceUpdateRequest sgsDeviceRequest = new SgsDeviceUpdateRequest();
            sgsDeviceRequest.setReqTime(new Date());
            sgsDeviceRequest.setLoginChannel(AppName.SGT.getNumber());
            sgsDeviceRequest.setInitiationID( SerialNoUtil.generateSerialNo(AppName.SGT));
            sgsDeviceRequest.setDeviceId(deviceId);
//            sgsDeviceRequest.setMchId(SgTcpServer.sgsDeviceService.queryDeviceInfo( ) ); //根据设备ID查询商户ID,需要
            //只有交互成功才更新为在线状态
            if(deviceState.equals( EnumLoginCheckResponseResult.SUCCESS.getStateCode() )){
                log.info("更新设备{}在线",deviceId);
                sgsDeviceRequest.setState(EnumDeviceState.ONLINE.getStateCode());
            }else if(deviceState.equals( EnumLoginCheckResponseResult.FAILURE.getStateCode()))
            {
                log.info("更新设备{}离线",deviceId);
                sgsDeviceRequest.setState(EnumDeviceState.OFFLINE.getStateCode());
            }else if( deviceState.equals( EnumLoginCheckResponseResult.UNREGISTER.getStateCode())){

                log.info("更新设备{}未注册",deviceId);
                return;
            }
            String tempDeviceState = sgsDeviceRequest.getState();
            SgTcpServer.sgsDeviceService.updateDeviceStateById(deviceId,tempDeviceState);
    }

}
